/*
*
* NMaker
*
* This class takes the data extracted from KMLReader and creates a
* NHood object for each row
*
*/
class NMaker {
  
  // attributes
  String[] nameArray, nnumArray, descArray, coordStringArray;
  String[][] censusDataArray, otherDataArray;
  
  // constructor method
  NMaker(String[][] fromKML, String[][] fromCensus, String[][] fromOther) {
    
   nameArray = fromKML[0];
   nnumArray = fromKML[1];
   descArray = fromKML[2];
   coordStringArray = fromKML[3];
   censusDataArray = fromCensus;   
   otherDataArray = fromOther;
    
  } // constructor method
  
  // this method creates an array of NHood objects for output
  NHood[] makeNHoods() {
  
    // initiate output array
    NHood[] out = new NHood[(nameArray.length)];
    
    // iterate through rows of data and create NHood object for each
    for (int i = 0; i < nameArray.length; i++) {
       
      // split entry from coordinate strings array on colon
      // this will only result in more than item if the neighbour hood
      // in question is composed of more than one non-contiguous polygon
      String[] coordStrings = split(coordStringArray[i], ":");
      ArrayList coordOut = new ArrayList();
      
      // iterate through the list of polygons
      for(int j = 0; j < coordStrings.length; j++) {
        
        // split the string of coordinates for each polygon into
        // individual 3-element coordinate lines
        String[] coordStringsArray = split(coordStrings[j], ' ');
        
        float[][] coords = new float[coordStringsArray.length - 1][2];
        String[] cString = new String[2];
        cString[0] = "0";
        
        // iterate through each line
        for (int k = 0; k < (coordStringsArray.length - 1); k++) { // note: use coordStringsArray.length - 1 b/c last coord has trailing space
          // split each line into individual elements
          String[] h = split(coordStringsArray[k], ',');
          // interate through individual elements, convert to floats, and store
          for (int l = 0; l < 2; l++) {
            // remove numbers before decimal point to maintain precision
            cString[1] = split(h[l], ".")[1]; 
            // check if coordinate is negative
            if(float(h[l]) < 0) {
              coords[k][l] = -float(join(cString, "."));
            } else {
              coords[k][l] = float(join(cString, "."));
            }
          } // for loop
        } // for loop
        
        // add coordinate matrix to output ArrayList
        coordOut.add(coords);
      } // for loop
      
      // create NHood object
      out[i] = new NHood(trim(nameArray[i]).toUpperCase(), descArray[i], nnumArray[i], coordOut);
      
      // search censusDataArray for neighbourhood's census data and import to NHood object
      for(int m = 0; m < censusDataArray.length; m++) {
        
        // compare neighbourhood name with name in censusDataArray; if the same, import data
        if(out[i].name.equals(censusDataArray[m][0])) {
          
          out[i].importCensusData(censusDataArray[m]);
          break;
        } // if
        
        // some "neighbourhoods" in KML file don't have census data; call below
        // method for these neighbourhoods
        // (ALSO: is there a better way to code this then below? The whole m == (censusDataArray.length - 1)
        // thing seems a bit clumsy, but I'm really tired right now and don't feel like trying to fix it).
        if(m == (censusDataArray.length - 1)) { 
          out[i].importNullCensusData();
        } // if
        
      } // for
      
      // search otherDataArray for other neighbourhood data and import to NHood object
      for(int m = 0; m < otherDataArray.length; m++) {
        
        // compare neighbourhood name with name in censusDataArray; if the same, import data
        if(out[i].name.equals(otherDataArray[m][0])) {
          
          out[i].importOtherData(otherDataArray[m]);
          break;
        } // if
        
        // some "neighbourhoods" in KML file don't have census data; call below
        // method for these neighbourhoods
        // (ALSO: is there a better way to code this then below? The whole m == (censusDataArray.length - 1)
        // thing seems a bit clumsy, but I'm really tired right now and don't feel like trying to fix it).
        if(m == (otherDataArray.length - 1)) { 
          out[i].importNullOtherData();
        } // if
        
      } // for
      
    } // for 
    
  return out;
  
  } // makeNHoods method
  
  // calcNHoodMaxMins -- this method takes array of NHoods as input and calculates the max and
  // min values of various metrics
  float[][] calcNHoodMaxMin(NHood[] hoods) {
    
    // initialize output
    // this array is formatted so that the first index corresponds to a drawing mode
    // the first element in at each index is a minimum for that mode, the second element a maximum
    float[][] out = new float[17][2];
    
    // set initial min/max values -- this is totally hacky, needs improvement
    out[0][0] = 0; // this is the default drawing mode, and therefore has no minimum or maximum values
    out[0][1] = 0;
    out[1][0] = 100; // average age
    out[1][1] = 0;
    out[2][0] = 100; // percentage of renters
    out[2][1] = 0;
    out[3][0] = 100; // percentage of owners
    out[3][1] = 0;
    out[4][0] = 100; // people per dwelling
    out[4][1] = 0; 
    out[5][0] = 10000000; // average income
    out[5][1] = 0;
    out[6][0] = 10000000; // median income
    out[6][1] = 0;
    out[7][1] = 1000000; // number of structures
    out[7][1] = 0;
    out[8][1] = 100; // percentage single family
    out[8][1] = 0;
    out[9][1] = 100; // percent duplex/rowhouse
    out[9][1] = 0;
    out[10][1] = 100; // percent apartments > = 5 stories
    out[10][1] = 0;
    out[11][1] = 100; // percent apartments < 5 stories
    out[11][1] = 0;
    out[12][1] = 100; // percentage occupied
    out[12][1] = 0;
    out[13][1] = 100; // percent unoccupied
    out[13][1] = 0;
    out[14][1] = 100; // percent under construction
    out[14][1] = 0;
    out[15][1] = 100; // percent no longer in use
    out[15][1] = 0;
    out[15][1] = 100; // percent vacant lots
    out[15][1] = 0;
    
    // now iterate through neighbourhoods and find min and max values for each metric
    for(int i = 1; i < hoods.length; i++) {
      
      // average age
      if((hoods[i].aveAge < out[1][0]) && (hoods[i].aveAge != -1)) {
        out[1][0] = hoods[i].aveAge;
      }
      if(hoods[i].aveAge > out[1][1]) {
        out[1][1] = hoods[i].aveAge;
      }
      // percent renters
      if((hoods[i].percentRent < out[2][0]) && (hoods[i].percentRent != -1)) {
        out[2][0] = hoods[i].percentRent;
      }
      if(hoods[i].percentRent > out[2][1]) {
        out[2][1] = hoods[i].percentRent;
      }
      // percent owners
      if((hoods[i].percentOwn < out[3][0]) && (hoods[i].percentOwn != -1)) {
        out[3][0] = hoods[i].percentOwn;
      }
      if(hoods[i].percentOwn > out[3][1]) {
        out[3][1] = hoods[i].percentOwn;
      }
      // people per dwelling
      if((hoods[i].peoplePerDwelling < out[4][0]) && (hoods[i].peoplePerDwelling != -1)) {
        out[4][0] = hoods[i].peoplePerDwelling;
      }
      if(hoods[i].peoplePerDwelling > out[4][1]) {  
        out[4][1] = hoods[i].peoplePerDwelling;
      }
      // average income
      if((hoods[i].aveIncome < out[5][0]) && (hoods[i].aveIncome != -1)) {
        out[5][0] = hoods[i].aveIncome;
      }
      if(hoods[i].aveIncome > out[5][1]) {  
        out[5][1] = hoods[i].aveIncome;
      }
      // median income
      if((hoods[i].medianIncome < out[6][0]) && (hoods[i].medianIncome != -1)) {
        out[6][0] = hoods[i].medianIncome;
      }
      if(hoods[i].medianIncome > out[6][1]) {  
        out[6][1] = hoods[i].medianIncome;
      }
      // number of structures
      if((hoods[i].totalStructures < out[7][0]) && (hoods[i].totalStructures != -1)) {
        out[7][0] = hoods[i].totalStructures;
      }
      if(hoods[i].totalStructures > out[7][1]) {  
        out[7][1] = hoods[i].totalStructures;
      }
      // percent single family
      if((hoods[i].percentSingleDetached < out[8][0]) && (hoods[i].percentSingleDetached != -1)) {
        out[8][0] = hoods[i].percentSingleDetached;
      }
      if(hoods[i].percentSingleDetached > out[8][1]) {  
        out[8][1] = hoods[i].percentSingleDetached;
      }
      // percent rowhouse/duplex
      if((hoods[i].percentDuplexRowHouse < out[9][0]) && (hoods[i].percentDuplexRowHouse != -1)) {
        out[9][0] = hoods[i].percentDuplexRowHouse;
      }
      if(hoods[i].percentDuplexRowHouse > out[9][1]) {  
        out[9][1] = hoods[i].percentDuplexRowHouse;
      }
      // percent apartments greater than or equal to 5 stories
      if((hoods[i].percentApt5Plus < out[10][0]) && (hoods[i].percentApt5Plus != -1)) {
        out[10][0] = hoods[i].percentApt5Plus;
      }
      if(hoods[i].percentApt5Plus > out[10][1]) {  
        out[10][1] = hoods[i].percentApt5Plus;
      }
      // percent apartments less than 5 stories
      if((hoods[i].percentAptLess5 < out[11][0]) && (hoods[i].percentAptLess5 != -1)) {
        out[11][0] = hoods[i].percentAptLess5;
      }
      if(hoods[i].percentAptLess5 > out[11][1]) {  
        out[11][1] = hoods[i].percentAptLess5;
      }
      
      // percent occupied
      if((hoods[i].percentOccupied < out[12][0]) && (hoods[i].percentOccupied != -1)) {
        out[12][0] = hoods[i].percentOccupied;
      }
      if(hoods[i].percentOccupied > out[12][1]) {  
        out[12][1] = hoods[i].percentOccupied;
      }
      // percent unoccupied
      if((hoods[i].percentUnoccupied < out[13][0]) && (hoods[i].percentUnoccupied != -1)) {
        out[13][0] = hoods[i].percentUnoccupied;
      }
      if(hoods[i].percentUnoccupied > out[13][1]) {  
        out[13][1] = hoods[i].percentUnoccupied;
      }
      // percent under construction
      if((hoods[i].percentUnderConstruction < out[14][0]) && (hoods[i].percentUnderConstruction != -1)) {
        out[14][0] = hoods[i].percentUnderConstruction;
      }
      if(hoods[i].percentUnderConstruction > out[14][1]) {  
        out[14][1] = hoods[i].percentUnderConstruction;
      }
      // percent no longer in use
      if((hoods[i].percentNoLongerInUse < out[15][0]) && (hoods[i].percentNoLongerInUse != -1)) {
        out[15][0] = hoods[i].percentNoLongerInUse;
      }
      if(hoods[i].percentNoLongerInUse > out[15][1]) {  
        out[15][1] = hoods[i].percentNoLongerInUse;
      }
      // percent vacant lots
      if((hoods[i].percentVacantLot < out[16][0]) && (hoods[i].percentVacantLot != -1)) {
        out[16][0] = hoods[i].percentVacantLot;
      }
      if(hoods[i].percentVacantLot > out[16][1]) {  
        out[16][1] = hoods[i].percentVacantLot;
      }
    } // for loop
    
    // return output array
    return out;
    
  } // calcNHoodMaxMin method
  
} // class
